﻿using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Collections.Generic;
using AgencyEntityLib.BaseEntity;
using Ecopsy.Tools;
using FormControllers;
using Ecopsy.DataTier;
using System.ComponentModel;
using System.Text;
using System.IO;

namespace Samples
{
    public enum CheckBoxType { Classic, RadioButton }

    public class TreeNodeDictionaryControl : TreeView
    {
        /// <summary>
        /// Тип чекбоксов дерева 
        /// Classic - множественный выбор значений 
        /// RadioButton- 
        /// </summary>

        private const string ControlPref = "PropertyTreeView";
        private const string NamespacePref = "Samples";
        private const string SelectedNodePref = "_SelNode";
        private const string TreeDictionaryPref = "_TreeDictionaryID";
        private const string TreeDictionaryFolderPref = "_TreeDictionaryFolderID";

        private ScriptManager sm;



        string _SelectedNodeID = Guid.NewGuid().ToString();
        //Id скрытого поля - хранилище SelectedNode
        protected string hf_SelectedNodeID { get { return this.ID + SelectedNodePref; } }
        //Id скрытого поля - хранилище TreeDictionaryID
        protected string hf_TreeDictionaryID { get { return this.ID + TreeDictionaryPref; } }

        //Id скрытого поля - хранилище TreeDictionaryFolderID
        protected string hf_TreeDictionaryFolderID { get { return this.ID + TreeDictionaryFolderPref; } }

        protected override void Render(HtmlTextWriter writer)
        {
            if (!this.DesignMode)
            {
                if (null == _TreeDictionaryItemValue)
                    return;

                //sm.RegisterScriptDescriptors(this);
                writer.Write("<div id='" + this.ID + "'>");
                writer.Write("<input type='hidden' name='" + hf_SelectedNodeID + "' id='" + hf_SelectedNodeID + "' value='" + SelectedNodeList + "' />");
                writer.Write("<input type='hidden' name='" + hf_TreeDictionaryID + "' id='" + hf_TreeDictionaryID + "' value='" + TreeDictionaryID + "' />");
                writer.Write("<input type='hidden' name='" + hf_TreeDictionaryFolderID + "' id='" + hf_TreeDictionaryFolderID + "' value='" + TreeDictionaryFolderID + "' />");
                base.Render(writer);
                writer.Write("</div>");
                return;
            }
            base.Render(writer);
        }


        #region Property

        /// <summary>
        /// Событие - прорисовка ноды - позволяет перекрвть рисование ноды
        /// </summary>
        public Func<TreeDictionaryItem, string> OnNodeRendering;



        public Func<TreeDictionaryItem> _TreeDictionaryItemSource = null;

        /// <summary>
        /// Тип справочника - если  не указана функция источник  - формируется по соответсвующему значению в TreeDictionaryItemValue
        /// </summary>
        protected TreeDictionaryItem TreeDictionaryItem
        {
            get
            {
                if (null != _TreeDictionaryItemSource)
                    return _TreeDictionaryItemSource();
                if (null == _TreeDictionaryItemValue)
                    return null;
                return TreeDictionaryItem.GetTreeDictionary(_TreeDictionaryItemValue.TreeDictionaryFolderID, _TreeDictionaryItemValue.ID);
            }


        }
        /// <summary>
        /// Значение считанное из дерева
        /// </summary>        
        private TreeDictionaryItemValue _TreeDictionaryItemValue = null;
        public TreeDictionaryItemValue TreeDictionaryItemValue
        {
            get { return GetTreeDictionaryItemValue(); }
            set { _TreeDictionaryItemValue = value; }
        }

        [DefaultValue(CheckBoxType.Classic)]
        public CheckBoxType TreeCheckBoxType { get; set; }

        
        private string _NodeClass = "TreeNode";
        public string NodeClass { get { return _NodeClass; } set { _NodeClass = value; } }
                
        private string _NodeClassSelected = "TreeNodeActive";
        public string NodeClassSelected { get { return _NodeClassSelected; } set { _NodeClassSelected = value; } }

        #endregion

        /// <summary>
        /// Точка входа 
        /// </summary>
        /// <param name="e"></param>
        protected override void OnDataBinding(EventArgs e)
        {
            if (!this.DesignMode)
            {
                // определить делегат поставляющий класс определяющий формат ноды в дереве
                Func<TreeEntitySingle, F_TreeDataSource.F_TreeDataSourceView.F_TreeHierarchyData> formatter = delegate(TreeEntitySingle _tr)
                {
                    return (F_TreeDataSource.F_TreeDataSourceView.F_TreeHierarchyData)new TreeNodeFormatter_Rb(_tr, RbNodeRenderContext);
                };

                if (null != TreeDictionaryItemValue)
                {

                    F_TreeDataSource Source = new F_TreeDataSource(TreeDictionaryItem, formatter);
                    this.DataSource = Source;
                }

            }
            base.OnDataBinding(e);

        }

        /// <summary>
        /// Рендеринг контекст для RB
        /// </summary>
        private TreeNodeFormatter_Rb.TreeRbContext RbNodeRenderContext
        {
            get
            {
                return new TreeNodeFormatter_Rb.TreeRbContext()
                {
                    DivClass = "",
                    NodeClass = NodeClass,
                    HfId = "",
                    OnChBind = MyOnChBind,
                    OnNodeRendering = MyNodeRendering
                };
            }
        }

        protected virtual bool MyOnChBind(TreeEntitySingle _nd)
        {
            if (null == TreeDictionaryItemValue)
                return false;

            if (null == _nd.ParentNode)
                return false;

            TreeDictionaryItem nd = (TreeDictionaryItem)_nd;

            HashSet<DictionaryItem> ds = TreeDictionaryItemValue.ValueToHashSet();

            return (ds.Contains(nd as DictionaryItem));


        }

        /// <summary>
        /// Прорисовка ноды дерева
        /// </summary>
        /// <param name="_nd"></param>
        /// <returns></returns>
        protected virtual string MyNodeRendering(TreeEntitySingle _nd)
        {
            ///Строим Writer
            StringBuilder sb;
            MemoryStream ms = new MemoryStream();
            sb = new StringBuilder();
            StringWriter sw = new StringWriter(sb, System.Globalization.CultureInfo.InvariantCulture);
            System.Web.UI.Html32TextWriter w = new System.Web.UI.Html32TextWriter(sw);

            ///Формируем табличку - представляющую ноду
            Table tbl = new Table();
            TableRow rw = new TableRow();
            TableCell cell = new TableCell();

            //Получаем контрол 
            Control c = GetNdControl(_nd);
            cell.Controls.Add(c);

            Button Btn = new Button();
            Btn.Text = "++";
            cell.Controls.Add(Btn);

            rw.Cells.Add(cell);
            tbl.Rows.Add(rw);
            tbl.RenderControl(w);



            return sb.ToString();
        }

        /// <summary>
        /// Возвращает контрол - если конечный элемент дерева чекбокс иначе лабел
        /// </summary>
        /// <param name="_nd"></param>
        /// <returns></returns>
        private Control GetNdControl(TreeEntitySingle _nd)
        {
            //////Формируем лабель 
            LinkButton lab = new LinkButton() { Text = ((TreeDictionaryItem)_nd).Name };            
            lab.ID = _nd.ID; 
            lab.Attributes.Add("onmousedown", "ShowMenu(event);");            
            
            //string[] Att = { this.NodeClass,this.NodeClassSelected, this.ID, _nd.ID, hf_SelectedNodeID };
            //OnTreeLabelClick(ChTree_CSS,ChTree_CSS_Selected, DIV_ID, LB_ID, SelectedNodeID)
            //lab.Attributes.Add("onclick", string.Format("OnTreeLabelClick('{0}','{1}',{2}','{3}','{4}');", Att));

            string[] Att = { this.NodeClass, this.NodeClassSelected, this.ID, _nd.ID, hf_SelectedNodeID };
            lab.OnClientClick = string.Format("OnTreeLabelClick('{0}','{1}','{2}','{3}','{4}');", Att);
            //lab.Attributes.Add("onclick", string.Format("OnTreeLabelClick('{0}','{1}','{2}','{3}','{4}');", Att));

            lab.CssClass = NodeClass;
            return lab;

        }

        public string[] SelectedListId
        {
            get
            {
                string s = HttpContext.Current.Request.Form[hf_SelectedNodeID];
                List<string> l = new List<string>();
                foreach (string i in s.Split(",".ToCharArray()))
                {
                    if (i.Length > 0)
                        l.Add(i);
                }
                return l.ToArray();

            }

        }

        protected string TreeDictionaryID
        {
            get
            {
                if (_TreeDictionaryItemValue == null)
                    return HttpContext.Current.Request.Form[hf_TreeDictionaryID];
                return TreeDictionaryItemValue.ID;
            }
        }

        protected string _SelectedNodeAsString = string.Empty;

        protected string SelectedNodeList
        {
            get
            {
                if (_TreeDictionaryItemValue == null)
                    return HttpContext.Current.Request.Form[hf_SelectedNodeID];
                return _SelectedNodeAsString;
            }
        }

        protected string TreeDictionaryFolderID
        {
            get
            {
                if (_TreeDictionaryItemValue == null)
                    return HttpContext.Current.Request.Form[hf_TreeDictionaryFolderID];

                return TreeDictionaryItemValue.TreeDictionaryFolderID;
            }
        }

        /// <summary>
        /// Стоит значение на основе TreeDictionaryID,TreeDictionaryFolderID,SelectedListId 
        /// </summary>
        /// <returns></returns>
        protected virtual TreeDictionaryItemValue GetTreeDictionaryItemValue()
        {
            if (null != _TreeDictionaryItemValue)
                return _TreeDictionaryItemValue;

            if (SelectedListId.Length == 0)
                return null;

            TreeDictionaryItemValue res = TreeDictionaryItem.BuildValue(SelectedListId[0]);
            foreach (string i in SelectedListId)
            {
                TreeDictionaryItemValue av = TreeDictionaryItem.BuildValue(i);
                res.AddValue(av);
            }
            return res;
        }

    }

    public class PropertyTreeView : TreeNodeDictionaryControl 
    {
        /// <summary>
        /// Прорисовка ноды дерева
        /// </summary>
        /// <param name="_nd"></param>
        /// <returns></returns>
        protected override  string MyNodeRendering(TreeEntitySingle _nd)
        {
            ///Строим Writer
            StringBuilder sb;
            MemoryStream ms = new MemoryStream();
            sb = new StringBuilder();
            StringWriter sw = new StringWriter(sb, System.Globalization.CultureInfo.InvariantCulture);
            System.Web.UI.Html32TextWriter w = new System.Web.UI.Html32TextWriter(sw);

            ///Формируем табличку - представляющую ноду
            Table tbl = new Table();
            TableRow rw = new TableRow();
            TableCell cell = new TableCell();

            //Получаем контрол 
            Control c = GetNdControl(_nd);
            cell.Controls.Add(c);

            Button Btn = new Button();
            Btn.Text = "++";
            cell.Controls.Add(Btn);

            rw.Cells.Add(cell);
            tbl.Rows.Add(rw);
            tbl.RenderControl(w);



            return sb.ToString();
        }

        /// <summary>
        /// Возвращает контрол - если конечный элемент дерева чекбокс иначе лабел
        /// </summary>
        /// <param name="_nd"></param>
        /// <returns></returns>
        private Control GetNdControl(TreeEntitySingle _nd)
        {
            if (_nd.ChildNodes.Count == 0)
            {
                CheckBox ch = new CheckBox();
                ch.ID = _nd.ID;
                if (MyOnChBind(_nd))
                {
                    ch.Checked = true;
                    _SelectedNodeAsString = _SelectedNodeAsString + _nd.ID + ",";
                }
                ch.Text = ((TreeDictionaryItem)_nd).Name;
                string[] Att = { this.ID, _nd.ID, hf_SelectedNodeID };
                ch.InputAttributes.Add("onclick", string.Format("OnTreeRbClick('{0}','{1}','{2}')", Att));
                return ch;
            }

            //////Формируем лабель 
            Label lab = new Label() { Text = ((TreeDictionaryItem)_nd).Name };
            lab.ID = "lbl_" + _nd.ID.Replace("-", "");
            lab.Attributes.Add("onmousedown", "ShowMenu(event);");
            lab.CssClass = NodeClass;
            return lab;

        }

    }
}